<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #map {
            width: 900px;
            height: 700px;
            background-color: lightgreen;
            margin: 20px auto;
            position: relative;
        }
    </style>
</head>
<body>
    <div id="map"></div>

    <script>
        /* 
            食物是一个对象，小蛇也是一个对象，最后成游戏对象
        */
        // 更整体一点
        // 一、食物对象  
        // 1.产生随机对象
        ((function() {
            // 1.自定义构造函数
            function Food(width, height, color, x, y) {
                this.width = width || 20;// 设置默认的小方块的宽度
                this.height = height || 20;// 设置默认的小方块的高度
                this.color = color || "pink";
                // 需要随机产生的left和top值
                this.x = x || 0;
                this.y = y || 0;
                // 创建一个div盒子--->食物
                this.element = document.createElement("div");
            }

            // 2.在原型上初始化食物
            Food.prototype.init = function(map) {
                // ① 设置小方块的样式
                var div = this.element;
                div.style.width = this.width + "px";
                div.style.height = this.height + "px";
                div.style.backgroundColor = this.color;
                div.style.position = "absolute";
                // 设置随机坐标
                this.x = Math.floor(Math.random() * (map.offsetWidth / this.width)) * this.width;
                this.y = Math.floor(Math.random() * (map.offsetHeight / this.height)) * this.height;
                div.style.left = this.x + "px";
                div.style.top = this.y + "px";
                // ② 把小方块添加到map中
                map.appendChild(div);
            }
            // 3.food暴露给window
            window.Food = Food;
        })());

        // 二、小蛇对象
        ((function() {
            var elements = [];//存放蛇
            // 1.小蛇的构造函数
            function Snake(width, height, direction) {
                // 小蛇的每个部位的宽高
                this.width = width || 20;
                this.height = height || 20;
                // 方向
                this.direction = direction || "right";
                // 小蛇身体刻度
                this.body = [
                    {x:3, y:1, color:"red"},//小蛇的头部
                    {x:2, y:1, color:"orange"},//小蛇的身体
                    {x:1, y:1, color:"orange"},//小蛇的身体
                ];
            }

            // 2.在原型对象上初始化小蛇
            Snake.prototype.init = function(map) {
                // 先删除再创建
                remove();
                // ① 遍历的创建div
                for(var i = 0; i < this.body.length; i++) {
                    // 每一个部位的刻度
                    var obj = this.body[i];
                    // 创建div并且添加样式
                    var div = document.createElement("div");
                    div.style.width = this.width + "px";
                    div.style.height = this.height + "px";
                    div.style.position = "absolute";
                    div.style.backgroundColor = obj.color;
                    // 设置坐标
                    div.style.left = obj.x * this.width + "px";
                    div.style.top = obj.y * this.height + "px";
                    map.appendChild(div);
                    // 把蛇添加到数组里面
                    elements.push(div);
                }
            };

            // 3.添加方法---移动小蛇
            Snake.prototype.move = function(food, map) {
                // ① 改变小蛇身体的坐标，因为小蛇头部判断方向
                for(var i = this.body.length - 1; i > 0; i--) {
                    // 让第三块x的坐标 = 第二块x的坐标
                    this.body[i].x = this.body[i - 1].x;
                    this.body[i].y = this.body[i - 1].y;
                }
                // ② 判断小蛇头部的坐标
                switch(this.direction) {
                    case "right":
                        this.body[0].x++;
                        break;
                    case "left":
                        this.body[0].x--;
                        break;
                    case "top":
                        this.body[0].y--;
                        break;
                    case "bottom":
                        this.body[0].y++;
                        break;
                }
                // ③ 最后：判断小蛇是否吃到食物--->头部坐标和食物坐标一致
                // 头部坐标
                var headX = this.body[0].x * this.width;
                var headY = this.body[0].y * this.height;
                // 食物的坐标
                var foodX = food.x;
                var foodY = food.y;
                if(headX == foodX && headY == foodY) {
                    // 追加一节蛇的身体到body的最后
                    var last = this.body[this.body.length - 1];//复制小蛇的尾巴
                    // 添加到数组
                    this.body.push({
                        x: last.x,
                        y: last.y,
                        color: last.color
                    });
                    // 食物吃完了要刷新位置
                    food.init(map);
                }
            }

            // ④ 封装删除小蛇的函数
            function remove() {
                for(var i = elements.length - 1; i >= 0; i--) {
                    // 数组里的每一个部位
                    var ele = elements[i];
                    // 在map中删除div
                    ele.parentNode.removeChild(ele);
                    // 删数组的div
                    elements.splice(i, 1);
                }
            }
            window.Snake = Snake;
        })());

        // 三、游戏对象
        ((function() {
            var that;
            // 1.游戏的构造函数
            function Game(map) {
                this.food = new Food();
                this.snake = new Snake();
                this.map = map;
                that = this;
            }
            // 2.初始化游戏
            Game.prototype.init = function() {
                this.food.init(this.map);
                this.snake.init(this.map);
                // 调用
                this.runSnake(this.map);
                // 调用按键方法
                this.bindKey();
            }
            // 3.添加方法让小蛇跑起来
            Game.prototype.runSnake = function(map) {
                var timeId = setInterval(function() {
                    that.snake.move(that.food, that.map);
                    that.snake.init(map);
                    // 判断横纵坐标最大最小值
                    var maxX = map.offsetWidth / that.snake.width;
                    var maxY = map.offsetHeight / that.snake.height;

                    // 蛇头的坐标
                    var headX = that.snake.body[0].x;
                    var headY = that.snake.body[0].y;

                    if(headX < 0 || headX >= maxX) {
                        // 清楚定时器
                        clearInterval(timeId);
                        alert("你太菜了！");
                    }
                    if(headY < 0 || headY >= maxY) {
                        // 清楚定时器
                        clearInterval(timeId);
                        alert("你太菜了！");
                    }
                }, 200)
            }
            // 4.设置用户的按键，改变小蛇移动的方向
            Game.prototype.bindKey = function() {
                document.addEventListener("keydown", function(e) {
                    switch(e.keyCode) {
                        case 37:
                            that.snake.direction = "left";
                            break;
                        case 38:
                            that.snake.direction = "top";
                            break;
                        case 39:
                            that.snake.direction = "right";
                            break;
                        case 40:
                            that.snake.direction = "bottom";
                            break;
                    }
                })
            }
            window.Game = Game;
        })());

        // 最终
        var game = new Game(document.getElementById("map"));
        game.init();
    </script>
</body>
</html>